namespace AgentJohnson.DocumentThrownExceptions
{
  using System;
  using System.Text;
  using JetBrains.Annotations;
  using Resharper.Abstractions.CodeDom.Comments;
  using Resharper.Abstractions.CodeDom.Statements.ThrowStatements;
  using Resharper.Abstractions.CodeDom.TypeMembers;
  using Resharper.Abstractions.Daemons;

  /// <summary>Defines the <see cref="DocumentThrownExceptionQuickFix"/> class.</summary>
  [QuickFix]
  public class DocumentThrownExceptionQuickFix : QuickFixBase
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="DocumentThrownExceptionQuickFix"/> class.</summary>
    /// <param name="highlight">The highlight.</param>
    public DocumentThrownExceptionQuickFix(DocumentThrownExceptionHighlight highlight) : base(highlight)
    {
      this.ThrowStatement = highlight.ThrowStatement;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the throw statement.
    /// </summary>
    /// <value>The throw statement.</value>
    protected ThrowStatement ThrowStatement { get; set; }

    #endregion

    #region Methods

    /// <summary>Determines whether this instance can execute the specified action context.</summary>
    /// <param name="context">The action context.</param>
    /// <returns><c>true</c> if this instance can execute the specified action context; otherwise, <c>false</c>.</returns>
    protected override bool CanFix(CanFixContext context)
    {
      return true;
    }

    /// <summary>Executes the action.</summary>
    /// <param name="context">The execute context.</param>
    protected override void Fix(FixContext context)
    {
      if (context == null)
      {
        throw new ArgumentNullException("context");
      }

      var anchor = this.ThrowStatement.GetContainingTypeMember();
      if (anchor == null)
      {
        return;
      }

      var exceptionTypeName = this.ThrowStatement.EscapedExceptionTypeName;
      var n = exceptionTypeName.LastIndexOf('.');
      if (n >= 0)
      {
        exceptionTypeName = exceptionTypeName.Substring(n + 1);
      }

      var code = new StringBuilder(string.Format("\r\n <exception cref=\"{0}\">{1}</exception>", exceptionTypeName, this.ThrowStatement.ExceptionMessage));
      anchor.FormatComment(code);

      var comment = anchor.Comment;
      if (comment != null)
      {
        code.Insert(0, comment.ToString());
      }
      else
      {
        code.Remove(0, 1);
      }

      code.Append("\nvoid foo(){}");

      var dummy = context.Factory.CreateTypeMember(code.ToString());
      if (dummy == null)
      {
        return;
      }

      var newComment = dummy.Comment;
      if (newComment != null)
      {
        anchor.Comment = newComment;
      }
    }

    /// <summary>Gets the text.</summary>
    /// <returns>Returns the text.</returns>
    protected override string GetText()
    {
      return string.Format("Add exception description for \"{0}\" [Agent Johnson]", this.ThrowStatement.ExceptionTypeName);
    }

    #endregion
  }
}